package sg.edu.nus.iss.billing.gui;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.text.MessageFormat;
import java.util.Properties;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import sg.edu.nus.iss.billing.BillingApplication;
import sg.edu.nus.iss.billing.BillingConstants;
import sg.edu.nus.iss.billing.BillingConstants.SystemState;
import sg.edu.nus.iss.billing.controller.ComplaintController;
import sg.edu.nus.iss.billing.exceptions.ControllerException;
import sg.edu.nus.iss.billing.model.account.Account;
import sg.edu.nus.iss.billing.model.complaint.Complaint;
import sg.edu.nus.iss.billing.model.complaint.Complaint.ComplaintStatus;

/**
 * @author Yeo Hee Ling, Ananda, Saravana
 *
 */
public class ComplaintPanel extends JPanel implements ActionListener {
	private static final long serialVersionUID = 1L;
	
	//Declaration of local variables
	private Account account;
	private Complaint complaint;
	private Properties properties;
	private BillingApplication billingAppl;
	private JPanel searchResultPanel;
	private JComboBox cbComplaintStatus;
	private JButton btnSave, btnEdit, btnClear, btnSearchResult, btnUpdate;
	private JTextArea txtDescription, txtRemarks;
	private JTextField txtComplaintId, txtAccount, txtAgent, txtLoggedDate, txtClosedDate;
	private JLabel lblComplaintId, lblAccount, lblDescription, lblStatus, lblAgent, lblRemarks, lblLogDate, lblClosedDate;
	private String[] complaintStatusOption = {ComplaintStatus.PENDING.toString(), ComplaintStatus.CLOSED.toString()};
		
	// Class Constructor.
	public ComplaintPanel(BillingApplication billingAppl, SystemState selectedMode, Complaint complaint, JPanel searchResultPanel, Account account) {
		this.account = account;
		this.complaint = complaint;
		this.billingAppl = billingAppl;
		this.searchResultPanel = searchResultPanel;
		this.setOpaque(false);
		
		loadConfiguration();
		
		boolean editable = true;
		if(SystemState.COMPLAINT_VIEW == selectedMode)
			editable = false;
		
		JPanel complaintPanel = new JPanel ();
		complaintPanel.setOpaque(false);
		complaintPanel.setLayout(new BorderLayout());
		complaintPanel.add(registerEditComplaintPanel(selectedMode, editable), BorderLayout.CENTER);
        
        if(SystemState.COMPLAINT_UPDATE == selectedMode || SystemState.COMPLAINT_VIEW == selectedMode) {
        	populateComplaintDetails();
        }
        else if (SystemState.COMPLAINT_ADD == selectedMode) {
        	txtAccount.setText(account.getAccountNo());
        }
        
        add(complaintPanel);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == btnClear) {
			txtComplaintId.setText("");
			txtDescription.setText("");
			cbComplaintStatus.setSelectedIndex(0);
			txtRemarks.setText("");
			txtLoggedDate.setText("");
			txtClosedDate.setText("");
		}
		else if(e.getSource() == btnSave) {
			String description = txtDescription.getText().trim();
			String remarks = txtRemarks.getText().trim();
			String status = (String)cbComplaintStatus.getSelectedItem();
			String agent = BillingApplication.getUserSession().getPersonName();
			String cid;
			
			try {
				ComplaintController complaintController = new ComplaintController();
				cid = complaintController.addComplaint(account, description, status, agent, remarks);
				
				MessageFormat msgFormat = new MessageFormat(properties.getProperty("info.message.addSuccessfully"));
				Object[] complaintArgs = {cid};
				
				JOptionPane.showMessageDialog(this, msgFormat.format(complaintArgs), properties.getProperty("label.complaint.header.add"), JOptionPane.INFORMATION_MESSAGE);
				billingAppl.displayPage(searchResultPanel);
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.addComplaint"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}	
		else if(e.getSource() == btnUpdate) {
			String description = txtDescription.getText().trim();
			String remarks = txtRemarks.getText().trim();
			String status = (String)cbComplaintStatus.getSelectedItem();
			String agent = BillingApplication.getUserSession().getPersonName();
									
			try {
				complaint.setComplaintDescription(description);
				complaint.setComplaintRemarks(remarks);
				complaint.setComplaintStatus(status);
				complaint.setAgentName(agent);
				complaint.setClosedDate("");
				if (status == ComplaintStatus.CLOSED.toString()) {
					ComplaintController controller = new ComplaintController();
					String cltime = controller.generateDateTime();
					complaint.setClosedDate(cltime);
				}
				
				ComplaintController complaintController = new ComplaintController();
				complaintController.updateComplaint(complaint);
				JOptionPane.showMessageDialog(this, properties.getProperty("info.message.updateSuccessfully"), properties.getProperty("title.updateComplaint"), JOptionPane.INFORMATION_MESSAGE);
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.updateComplaint"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		else if(e.getSource() == btnEdit) {
			billingAppl.displayPage(new ComplaintPanel(billingAppl, SystemState.COMPLAINT_UPDATE, complaint, searchResultPanel,null));
		}
		else if(e.getSource() == btnSearchResult) {
			billingAppl.displayPage(searchResultPanel);
		}			
	}
	
	private void loadConfiguration() {
		try {
			properties = new Properties();
			FileInputStream in = new FileInputStream(BillingConstants.PROPERTIES_COMPLAINT);
			properties.load(in);
			in.close();
		}
		catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void populateComplaintDetails() {
		if(complaint != null) {
			txtComplaintId.setText(complaint.getComplaintId());
			txtAccount.setText(complaint.getAccountNo());
			txtDescription.setText(complaint.getComplaintDescription());
			cbComplaintStatus.setSelectedItem(complaint.getComplaintStatus().toString());
			txtAgent.setText(complaint.getAgentName());
			txtRemarks.setText(complaint.getComplaintRemarks());
			txtLoggedDate.setText(complaint.getLoggedDate().toString());
			txtClosedDate.setText(complaint.getClosedDate().toString());
	
		}
    }
	
	private JPanel registerEditComplaintPanel (SystemState selectedMode, boolean editable) {
		// 1. To determine the title of the complaint panel.
		String complaintPanelTitle = "";
		if(SystemState.COMPLAINT_ADD == selectedMode)
			complaintPanelTitle = properties.getProperty("title.addComplaint");
		else if(SystemState.COMPLAINT_VIEW == selectedMode)
			complaintPanelTitle = properties.getProperty("title.viewComplaint");
		else if(SystemState.COMPLAINT_UPDATE == selectedMode)
			complaintPanelTitle = properties.getProperty("title.updateComplaint");
		
		// 2. Construct Complaint Details Panel
		GridBagLayout complaintGridLayout = new GridBagLayout();
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = new Insets(5, 5, 5, 5);
		
		JPanel complaintDetailPanel = new JPanel(complaintGridLayout);
		complaintDetailPanel.setOpaque(false);
		
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.gridx = 0;
		constraints.gridy = 0;
		lblComplaintId = new JLabel(properties.getProperty("label.complaint.complaintId"));
		lblComplaintId.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblComplaintId, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 0;
		txtComplaintId = new JTextField(10);
		txtComplaintId.setText(" ");
		txtComplaintId.setEditable(false);
		txtComplaintId.setBorder(BorderFactory.createEmptyBorder());
		complaintDetailPanel.add(txtComplaintId, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		lblAccount = new JLabel(properties.getProperty("label.complaint.accountNo"));
		lblAccount.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblAccount, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 1;
		txtAccount = new JTextField(20);
		txtAccount.setEditable(false);
		complaintDetailPanel.add(txtAccount, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 2;
		lblDescription = new JLabel(properties.getProperty("label.complaint.description"));
		lblDescription.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblDescription, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 2;
		txtDescription = new JTextArea(5, 20);
		txtDescription.setEditable(editable);
		complaintDetailPanel.add(new JScrollPane(txtDescription), constraints);
		
		//Status
		constraints.gridx = 0;
		constraints.gridy = 3;
		lblStatus= new JLabel(properties.getProperty("label.complaint.complaintStatus"));
		lblStatus.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblStatus, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 3;
		cbComplaintStatus = new JComboBox(complaintStatusOption);
		if(SystemState.COMPLAINT_ADD == selectedMode || SystemState.COMPLAINT_VIEW == selectedMode)
			cbComplaintStatus.setEnabled(false);
		else
			cbComplaintStatus.setEnabled(true);
		complaintDetailPanel.add(cbComplaintStatus, constraints);
		
		// Agent
		constraints.gridx = 0;
		constraints.gridy = 4;
		lblAgent = new JLabel(properties.getProperty("label.complaint.agentName"));
		lblAgent.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblAgent, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 4;
		txtAgent = new JTextField(20);
		txtAgent.setText(BillingApplication.getUserSession().getPersonName());
		txtAgent.setEditable(false);
		complaintDetailPanel.add(txtAgent, constraints);
		
		//Remarks
		constraints.gridx = 0;
		constraints.gridy = 5;
		lblRemarks = new JLabel(properties.getProperty("label.complaint.remarks"));
		lblRemarks.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblRemarks, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 5;
		txtRemarks = new JTextArea(5, 20);
		txtRemarks.setEditable(editable);
		complaintDetailPanel.add(new JScrollPane(txtRemarks), constraints);
		
		//Logged Date
		constraints.gridx = 0;
		constraints.gridy = 6;
		lblLogDate = new JLabel(properties.getProperty("label.complaint.loggedDate"));
		lblLogDate.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblLogDate, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 6;
		txtLoggedDate = new JTextField(20);
		txtLoggedDate.setEditable(false);
		complaintDetailPanel.add(txtLoggedDate, constraints);
		
		//Closed Date
		constraints.gridx = 0;
		constraints.gridy = 7;
		lblClosedDate = new JLabel(properties.getProperty("label.complaint.closedDate"));
		lblClosedDate.setHorizontalAlignment(JLabel.RIGHT);
		complaintDetailPanel.add(lblClosedDate, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 7;
		txtClosedDate = new JTextField(20);
		txtClosedDate.setEditable(false);
		complaintDetailPanel.add(txtClosedDate, constraints);
		
		// Control Buttons - Clear, Save
		JPanel buttonPanel = new JPanel();
		buttonPanel.setOpaque(false);
		buttonPanel.setLayout(new GridLayout(0, 2, 5, 0));
		
		if(SystemState.COMPLAINT_ADD == selectedMode) {
			btnSave = new JButton(properties.getProperty("label.complaint.saveComplaint"));
			btnSave.addActionListener(this);
			btnClear = new JButton(properties.getProperty("label.complaint.clear"));
			btnClear.addActionListener(this);
			buttonPanel.add(btnSave);
			buttonPanel.add(btnClear);
		}
		else if(SystemState.COMPLAINT_VIEW == selectedMode) {
			btnEdit = new JButton(properties.getProperty("label.complaint.editComplaint"));
			btnEdit.addActionListener(this);
			btnSearchResult = new JButton(properties.getProperty("label.complaint.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnEdit);
			buttonPanel.add(btnSearchResult);
		}	
		else if(SystemState.COMPLAINT_UPDATE == selectedMode) {
			btnUpdate = new JButton(properties.getProperty("label.complaint.updateComplaint"));
			btnUpdate.addActionListener(this);
			btnSearchResult = new JButton(properties.getProperty("label.complaint.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnUpdate);
			buttonPanel.add(btnSearchResult);
		}
		constraints.gridx = 1;
		constraints.gridy = 8;
		complaintDetailPanel.add(buttonPanel, constraints);
		
		// 3. Construct Header Panel
		JPanel headerPanel = new JPanel();
		headerPanel.setOpaque(false);
		headerPanel.setLayout(new GridLayout(0, 1, 10, 10));
		
		JLabel msgLabel = new JLabel(complaintPanelTitle);
		msgLabel.setFont(new Font("Tahoma", Font.BOLD, 18));
		msgLabel.setHorizontalAlignment(SwingConstants.CENTER);
		headerPanel.add(msgLabel);
		
		ImageIcon imgDivider = new ImageIcon("./images/divider.jpg");
		JLabel lblDivider = new JLabel(imgDivider);
		headerPanel.add(lblDivider);
		
		JPanel complaintPanel = new JPanel();
		complaintPanel.setOpaque(false);
		complaintPanel.setLayout(new BorderLayout());
		complaintPanel.add(headerPanel, BorderLayout.NORTH);
		complaintPanel.add(complaintDetailPanel, BorderLayout.CENTER);
		
		return complaintPanel;
	}
}
